package lumis.portal.serialization.operation;

import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;

/**
 * Collection for config operations that depends on other previous operations
 *
 * @version $Revision: 5572 $ $Date: 2007-01-11 15:29:02 -0200 (Thu, 11 Jan 2007) $
 * @since 4.0.7
 */
public class DependentConfigOperationCollection<O extends ConfigOperation>
{
	private Map<O, Set<String>> configOperations = new HashMap<O, Set<String>>();
	private Map<String, Set<O>> configOperationsByDependency = new HashMap<String, Set<O>>();

	public void addDependentConfigOperation(String dependencyKey, O configOperation)
	{
		Set<String> dependencyKeys = configOperations.get(configOperation);
		if (dependencyKeys == null)
		{
			dependencyKeys = new HashSet<String>();
			configOperations.put(configOperation, dependencyKeys);
		}
		dependencyKeys.add(dependencyKey);
		
		Set<O> deserializations = configOperationsByDependency.get(dependencyKey);
		if (deserializations == null)
		{
			deserializations = new HashSet<O>();
			configOperationsByDependency.put(dependencyKey, deserializations);
		}
		deserializations.add(configOperation);
		
		/*Map<String, String> persistenceDependencyDescriptions = dependencyDescriptions.get(configOperation);
		if (persistenceDependencyDescriptions == null)
		{
			persistenceDependencyDescriptions = new HashMap<String, String>();
			dependencyDescriptions.put(configOperation, persistenceDependencyDescriptions);
		}*/
	}

	public void addDependentConfigOperation(Collection<String> dependencyKeys, O configOperation)
	{
		for (String dependencyKey : dependencyKeys)
			addDependentConfigOperation(dependencyKey, configOperation);
	}
	
	public Set<O> popDependentConfigOperations(String dependencyKey)
	{
		 Set<O> dependentConfigOperations = new HashSet<O>();

		 Set<O> candidateConfigOperations = configOperationsByDependency.get(dependencyKey);
		 if (candidateConfigOperations != null)
		 {
			 for (Iterator<O> iterator = candidateConfigOperations.iterator(); iterator.hasNext();)
			 {
				 O candidateConfigOperation = iterator.next();
				 Set<String> dependencyKeys = configOperations.get(candidateConfigOperation);
				 if (dependencyKeys != null)
					 dependencyKeys.remove(dependencyKey);
				 if (dependencyKeys == null || dependencyKeys.size() == 0) // no more dependencies
				 {
					 dependentConfigOperations.add(candidateConfigOperation);
					 configOperations.remove(candidateConfigOperation);
					 iterator.remove();
				 }
			 }
		 }
//		 if (candidateConfigOperations == null || candidateConfigOperations.size() == 0)
		 configOperationsByDependency.remove(dependencyKey);
		 
		 return dependentConfigOperations;
	}
	
	public boolean isEmpty()
	{
		return configOperations.isEmpty();
	}
	
	public Collection<String> getDependentKeys()
	{
		return new ArrayList<String>(configOperationsByDependency.keySet());
	}
}
